<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Highscore - Boost C++ 库 - 类型转换操作符</title>
<link rel="stylesheet" href="css/highscore.css" type="text/css">
<link rev="made" href="mailto:boris@highscore.de">
<link rel="home" href="frontpage.html" title="Boost C++ 库">
<link rel="up" href="frontpage.html" title="Boost C++ 库">
<link rel="prev" href="castoperators.html" title="第 15 章 类型转换操作符">
<link rel="chapter" href="introduction.html" title="第 1 章 简介">
<link rel="chapter" href="smartpointers.html" title="第 2 章 智能指针">
<link rel="chapter" href="functionobjects.html" title="第 3 章 函数对象">
<link rel="chapter" href="eventhandling.html" title="第 4 章 事件处理">
<link rel="chapter" href="asio.html" title="第 5 章 异步输入输出">
<link rel="chapter" href="asio.html" title="第 6 章 异步输入输出">
<link rel="chapter" href="asio.html" title="第 7 章 异步输入输出">
<link rel="chapter" href="interprocesscommunication.html" title="第 8 章 进程间通讯">
<link rel="chapter" href="filesystem.html" title="第 9 章 文件系统">
<link rel="chapter" href="castoperators.html" title="第 10 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 11 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 12 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 13 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 14 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 15 章 类型转换操作符">
<link rel="chapter" href="castoperators.html" title="第 16 章 类型转换操作符">
<link rel="section" href="castoperators.html#castoperators_general" title="16.1. 概述">
<link rel="section" href="castoperators.html#castoperators_conversion" title="16.2. Boost.Conversion">
<link rel="section" href="castoperators.html#castoperators_numeric_conversion" title="16.3. Boost.NumericConversion">
<meta http-equiv="pics-label" content='(pics-1.1 "http://www.icra.org/ratingsv02.html" l gen true for "http://www.highscore.de" r (nz 1 vz 1 lz 1 oz 1 cz 1) gen true for "http://highscore.de" r (nz 1 vz 1 lz 1 oz 1 cz 1))'>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta http-equiv="Content-Script-Type" content="text/javascript">
<link href="http://www.highscore.de/favicon.ico" rel="shortcut icon" type="image/vnd.microsoft.icon">
</head>
<body>
<div lang="zh" class="docbook chapter" title="第 16 章 类型转换操作符">
<p class="title">Boost C++ 库</p>
<script type="text/javascript">
          var titlepage = "导言";
        
      var titles = new Array(titlepage,
      
        "第 1 章 简介",
      
        "第 2 章 智能指针",
      
        "第 3 章 函数对象",
      
        "第 4 章 事件处理",
      
        "第 5 章 异步输入输出",
      
        "第 6 章 异步输入输出",
      
        "第 7 章 异步输入输出",
      
        "第 8 章 进程间通讯",
      
        "第 9 章 文件系统",
      
        "第 10 章 类型转换操作符",
      
        "第 11 章 类型转换操作符",
      
        "第 12 章 类型转换操作符",
      
        "第 13 章 类型转换操作符",
      
        "第 14 章 类型转换操作符",
      
        "第 15 章 类型转换操作符",
      
        "第 16 章 类型转换操作符",
      
      "");

      
          var titlehtml = "frontpage.html";
        
      var filenames = new Array(titlehtml,
      
        "introduction.html",
      
        "smartpointers.html",
      
        "functionobjects.html",
      
        "eventhandling.html",
      
        "asio.html",
      
        "asio.html",
      
        "asio.html",
      
        "interprocesscommunication.html",
      
        "filesystem.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
        "castoperators.html",
      
      "");

      
      document.open();
      document.write('<form action="" class="toc">');
      document.write('<select size="1" onchange="location.href=options[selectedIndex].value">');
      for (var i = 0; i < titles.length && i < filenames.length; ++i) {
        if (titles[i] != "" && filenames[i] != "") {
          document.write('<option');
          document.write(' value="' + filenames[i] + '"');
          var expr = new RegExp('[/\]' + filenames[i] + '$');
          if (expr.test(location.href)) {
            document.write(' selected="selected"');
          }
          document.write('>' + titles[i] + '<\/option>');
        }
      }
      document.write('<\/select>');
      document.write('<\/form>');
      document.close();
      
    </script><noscript><p class="toc"><a href="toc.html">目录</a></p></noscript>
<hr class="hrhead">
<h1 class="title">
<a name="castoperators"></a>第 16 章 类型转换操作符</h1>
<hr>
<div class="toc">
<h3>目录</h3>
<ul>
<li><span class="sect1"><a href="castoperators.html#castoperators_general">16.1 概述</a></span></li>
<li><span class="sect1"><a href="castoperators.html#castoperators_conversion">16.2 Boost.Conversion</a></span></li>
<li><span class="sect1"><a href="castoperators.html#castoperators_numeric_conversion">16.3 Boost.NumericConversion</a></span></li>
</ul>
</div>
<p class="license"><a href="http://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.zh" rel="license" target="_top"><img src="img/88x31_cc_logo.gif" alt="" width="88" height="31"></a> 该书采用 <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/de/deed.zh" rel="license" target="_top">Creative Commons License</a> 授权</p>
<hr>
<h2 class="title">
<a name="castoperators_general"></a>16.1. 概述</h2>
<div class="sect1"><p>C++标准定义了四种类型转换操作符: <code class="code">static_cast</code>,
    <code class="code">dynamic_cast</code>, <code class="code">const_cast</code> 和
    <code class="code">reinterpret_cast</code>。 Boost.Conversion 和 Boost.NumericConversion
    这两个库特别为某些类型转换定义了额外的类型转换操作符。</p></div>
<hr>
<h2 class="title">
<a name="castoperators_conversion"></a>16.2. Boost.Conversion</h2>
<div class="sect1">
<p><a class="link" href="http://www.boost.org/libs/conversion/">Boost.Conversion</a>
    库由两个文件组成。分别在 <code class="filename">boost/cast.hpp</code> 文件中定义了
    <code class="code">boost::polymorphic_cast</code> 和
    <code class="code">boost::polymorphic_downcast</code> 这两个类型转换操作符, 在 <code class="filename">boost/lexical_cast.hpp</code> 文件中定义了
    <code class="code">boost::lexical_cast</code>。</p>
<p><code class="code">boost::polymorphic_cast</code> 和
    <code class="code">boost::polymorphic_downcast</code> 是为了使原来用 <code class="code">dynamic_cast</code>
    实现的类型转换更加具体。具体细节，如下例所示。</p>
<pre class="programlisting">struct father 
{ 
  virtual ~father() { }; 
}; 

struct mother 
{ 
  virtual ~mother() { }; 
}; 

struct child : 
  public father, 
  public mother 
{ 
}; 

void func(father *f) 
{ 
  child *c = dynamic_cast&lt;child*&gt;(f); 
} 

int main() 
{ 
  child *c = new child; 
  func(c); 

  father *f = new child; 
  mother *m = dynamic_cast&lt;mother*&gt;(f); 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/16.2.1/main.cpp">下载源代码</a></li></ul>
<p>本例使用 <code class="code">dynamic_cast</code> 类型转换操作符两次: 在
    <code class="function">func()</code> 函数中，它将指向父类的指针转换为指向子类的指针。在
    <code class="function">main()</code> 中,
    它将一个指向父类的指针转为指向另一个父类的指针。第一个转换称为向下转换(downcast)，第二个转换称为交叉转换(cross
    cast)。</p>
<p>通过使用 Boost.Conversion 的类型转换操作符，可以将向下转换和交叉转换区分开来。</p>
<pre class="programlisting">#include &lt;boost/cast.hpp&gt; 

struct father 
{ 
  virtual ~father() { }; 
}; 

struct mother 
{ 
  virtual ~mother() { }; 
}; 

struct child : 
  public father, 
  public mother 
{ 
}; 

void func(father *f) 
{ 
  child *c = boost::polymorphic_downcast&lt;child*&gt;(f); 
} 

int main() 
{ 
  child *c = new child; 
  func(c); 

  father *f = new child; 
  mother *m = boost::polymorphic_cast&lt;mother*&gt;(f); 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/16.2.2/main.cpp">下载源代码</a></li></ul>
<p><code class="code">boost::polymorphic_downcast</code> 类型转换操作符只能用于向下转换。 它内部使用
    <code class="code">static_cast</code> 实现类型转换。 由于 <code class="code">static_cast</code>
    并不动态检查类型转换是否合法，所以 <code class="code">boost::polymorphic_downcast</code>
    应该只在类型转换是安全的情况下使用。 在调试(debug builds)模式下,
    <code class="code">boost::polymorphic_downcast</code> 实际上在 <code class="function">assert
    ()</code>函数中使用<code class="code"> dynamic_cast</code> 验证类型转换是否合法。
    请注意这种合法性检测只在定义了<code class="code">NDEBUG</code>宏的情况下执行，这通常是在调试模式下。</p>
<p>向下转换最好使用 <code class="code">boost::polymorphic_downcast</code>, 那么
    <code class="code">boost::polymorphic_cast</code> 就是交叉转换所需要的了。 由于
    <code class="code">dynamic_cast</code>
    是唯一能实现交叉转换的类型转换操作符，<code class="code">boost::polymorphic_cast</code> 内部使用了它。 由于
    <code class="code">boost::polymorphic_cast</code> 能够在错误的时候抛出
    <code class="exceptionname">std::bad_cast</code>
    类型的异常，所以优先使用这个类型转换操作符还是很有必要的。相反，<code class="code">dynamic_cast</code> 在类型转换失败使将返回0。
    避免手工验证返回值，<code class="code">boost::polymorphic_cast</code> 提供了自动化的替代方式。</p>
<p><code class="code">boost::polymorphic_downcast</code> 和
    <code class="code">boost::polymorphic_cast</code> 只在指针必须转换的时候使用；否则，必须使用
    <code class="code">dynamic_cast</code> 执行转换。 由于
    <code class="code">boost::polymorphic_downcast</code> 是基于
    <code class="code">static_cast</code>，所以它不能够，比如说，将父类对象转换为子类对象。 如果转换的类型不是指针，则使用
    <code class="code">boost::polymorphic_cast</code> 执行类型转换也没有什么意义，而在这种情况下使用
    <code class="code">dynamic_cast</code> 还会抛出一个
    <code class="exceptionname">std::bad_cast</code> 异常。</p>
<p>虽然所有的类型转换都可用 <code class="code">dynamic_cast</code> 实现，可
    <code class="code">boost::polymorphic_downcast</code> 和
    <code class="code">boost::polymorphic_cast</code> 也不是真正随意使用的。 Boost.Conversion
    还提供了另外一种在实践中很有用的类型转换操作符。 体会一下下面的例子。</p>
<pre class="programlisting">#include &lt;boost/lexical_cast.hpp&gt; 
#include &lt;string&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  std::string s = boost::lexical_cast&lt;std::string&gt;(169); 
  std::cout &lt;&lt; s &lt;&lt; std::endl; 
  double d = boost::lexical_cast&lt;double&gt;(s); 
  std::cout &lt;&lt; d &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/16.2.3/main.cpp">下载源代码</a></li></ul>
<p>类型转换操作符 <code class="code">boost::lexical_cast</code> 可将数字转换为其他类型。
    例子首先将整数169转换为字符串，然后将字符串转换为浮点数。</p>
<p><code class="code">boost::lexical_cast</code> 内部使用流(streams)执行转换操作。 因此，只有那些重载了
    <code class="methodname">operator&lt;&lt;()</code> 和
    <code class="methodname">operator&gt;&gt;()</code> 这两个操作符的类型可以转换。 使用
    <code class="code">boost::lexical_cast</code> 的优点是类型转换出现在一行代码之内，无需手工操作流(streams)。
    由于流的用法对于类型转换不能立刻理解代码含义, 而 <code class="code">boost::lexical_cast</code>
    类型转换操作符还可以使代码更有意义，更加容易理解。</p>
<p>请注意 <code class="code">boost::lexical_cast</code>
    并不总是访问流(streams)；它自己也优化了一些数据类型的转换。</p>
<p>如果转换失败，则抛出 <code class="exceptionname">boost::bad_lexical_cast</code>
    类型的异常，它继承自 <code class="exceptionname">std::bad_cast</code>。</p>
<pre class="programlisting">#include &lt;boost/lexical_cast.hpp&gt; 
#include &lt;string&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  try 
  { 
    int i = boost::lexical_cast&lt;int&gt;("abc"); 
    std::cout &lt;&lt; i &lt;&lt; std::endl; 
  } 
  catch (boost::bad_lexical_cast &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/16.2.4/main.cpp">下载源代码</a></li></ul>
<p>本例由于字符串 "abc" 不能转换为 <code class="type">int</code> 类型的数字而抛出异常。</p>
</div>
<hr>
<h2 class="title">
<a name="castoperators_numeric_conversion"></a>16.3. Boost.NumericConversion</h2>
<div class="sect1">
<p><a class="link" href="http://www.boost.org/libs/numeric/conversion/">Boost.NumericConversion</a>
    可将一种数值类型转换为不同的数值类型。 在C++里, 这种转换可以隐式地发生，如下面例所示。</p>
<pre class="programlisting">#include &lt;iostream&gt; 

int main() 
{ 
  int i = 0x10000; 
  short s = i; 
  std::cout &lt;&lt; s &lt;&lt; std::endl; 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/16.3.1/main.cpp">下载源代码</a></li></ul>
<p>由于从 <code class="type">int</code> 到 <code class="type">short</code> 的类型转换自动产生，所以本例编译没有错误。
    虽然本例可以运行，但结果由于依赖具体的编译器实现而结果无法预期。 数字<code class="literal">0x10000</code>对于变量
    <var>i </var>来说太大而不能存储在 <code class="type">short</code> 类型的变量中。
    依据C++标准，这个操作的结果是实现定义的("implementation defined")。 用Visual C++
    2008编译，应用程序显示的是<code class="computeroutput">0</code>。 <var>s</var>
    的值当然不同于 <var>i</var> 的值。</p>
<p>为避免这种数值转换错误，可以使用 <code class="classname">boost::numeric_cast</code>
    类型转换操作符。</p>
<pre class="programlisting">#include &lt;boost/numeric/conversion/cast.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  try 
  { 
    int i = 0x10000; 
    short s = boost::numeric_cast&lt;short&gt;(i); 
    std::cout &lt;&lt; s &lt;&lt; std::endl; 
  } 
  catch (boost::numeric::bad_numeric_cast &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/16.3.2/main.cpp">下载源代码</a></li></ul>
<p><code class="code">boost::numeric_cast</code> 的用法与C++类型转换操作符非常相似。 当然需要包含正确的头文件；就是
    <code class="filename">boost/numeric/conversion/cast.hpp</code>。</p>
<p><code class="code">boost::numeric_cast</code> 执行与C++相同的隐式转换操作。
    但是，<code class="code">boost::numeric_cast</code> 验证了在不改变数值的情况下转换是否能够发生。
    前面给的应用例子，转换不能发生，因而由于<code class="literal">0x10000</code>太大而不能存储在 <code class="type">short</code>
    类型的变量上，而抛出 <code class="exceptionname">boost::numeric::bad_numeric_cast</code>
    异常。</p>
<p>严格来讲，抛出的是
    <code class="exceptionname">boost::numeric::positive_overflow</code>
    类型的异常，这个类型特指所谓的溢出(overflow) - 在此例中是正数。 相应地，还存在着
    <code class="exceptionname">boost::numeric::negative_overflow</code>
    类型的异常，它特指负数的溢出。</p>
<pre class="programlisting">#include &lt;boost/numeric/conversion/cast.hpp&gt; 
#include &lt;iostream&gt; 

int main() 
{ 
  try 
  { 
    int i = -0x10000; 
    short s = boost::numeric_cast&lt;short&gt;(i); 
    std::cout &lt;&lt; s &lt;&lt; std::endl; 
  } 
  catch (boost::numeric::negative_overflow &amp;e) 
  { 
    std::cerr &lt;&lt; e.what() &lt;&lt; std::endl; 
  } 
} </pre>
<ul class="programlisting"><li><a class="programlisting" href="src/16.3.3/main.cpp">下载源代码</a></li></ul>
<p>Boost.NumericConversion 还定义了其他的异常类型，都继承自
    <code class="exceptionname">boost::numeric::bad_numeric_cast</code>。 因为
    <code class="exceptionname">boost::numeric::bad_numeric_cast</code> 继承自
    <code class="exceptionname">std::bad_cast</code>，所以 <code class="code">catch</code>
    处理也可以捕获这个类型的异常。</p>
</div>
</div>
<hr class="hrfoot">
<p class="copyright">版权 © 2008-2010 
        <a class="link" href="mailto:boris@highscore.de">Boris Schäling</a>
      </p>
</body>
</html>
